﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Extensions
{
    public static class StringExtensions
    {
        private static char[] UrlPathDelims = new char[2]
        {
            '?',
            '#'
        };

        private static readonly Regex StripHtmlRegEx = new Regex("<(.|\\n)*?>");

        private static readonly Regex StripBracketsRegEx = new Regex("\\[(.|\\n)*?\\]");

        private static readonly Regex StripBracesRegEx = new Regex("\\((.|\\n)*?\\)");

        private const int LowerCaseOffset = 32;

        private static readonly Regex InvalidVarCharsRegex = new Regex("[^A-Za-z0-9_]", RegexOptions.Compiled);

        private static readonly Regex InvalidVarRefCharsRegex = new Regex("[^A-Za-z0-9._]", RegexOptions.Compiled);

        private static readonly Regex SplitCamelCaseRegex = new Regex("([A-Z]|[0-9]+)", RegexOptions.Compiled);

        private static readonly Regex HttpRegex = new Regex("^http://", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

        private static readonly char[] SystemTypeChars = new char[3]
        {
            '<',
            '>',
            '+'
        };

        public static string BaseConvert(this string source, int from, int to)
        {
            string text = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            if (source.Length == 0)
            {
                throw new Exception($"Parameter: '{source}' is not valid integer (in base {from}).");
            }
            string text2 = (source[0] == '-') ? "-" : "";
            string text3 = (text2 == "") ? source : source.Substring(1);
            int length = text3.Length;
            if (length == 0)
            {
                throw new Exception($"Parameter: '{source}' is not valid integer (in base {from}).");
            }
            int num = 0;
            for (int i = 0; i < length; i++)
            {
                int num2 = text.IndexOf(text3[i]);
                if (num2 >= from)
                {
                    throw new Exception($"Parameter: '{source}' is not valid integer (in base {from}).");
                }
                num = num * from + num2;
            }
            if (to == 10 || num == 0)
            {
                return text2 + num.ToString();
            }
            string str = "";
            while (num > 0)
            {
                str = text[num % to].ToString() + str;
                num /= to;
            }
            return text2 + str;
        }

        public static string EncodeXml(this string value)
        {
            return value.Replace("<", "&lt;").Replace(">", "&gt;").Replace("&", "&amp;");
        }

        public static string EncodeJson(this string value)
        {
            return "\"" + value.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\r", "")
                .Replace("\n", "\\n") + "\"";
        }

        public static string DecodeJsv(this string value)
        {
            if (!string.IsNullOrEmpty(value) && value[0] == '"')
            {
                return value.Substring(1, value.Length - 2).Replace("\"\"", "\"");
            }
            return value;
        }

        public static string UrlEncode(this string text, bool upperCase = false)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }
            StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
            string format = upperCase ? "X2" : "x2";
            byte[] bytes = Encoding.UTF8.GetBytes(text);
            for (int i = 0; i < bytes.Length; i++)
            {
                byte b = bytes[i];
                if ((b >= 65 && b <= 90) || (b >= 97 && b <= 122) || (b >= 48 && b <= 57) || (b >= 44 && b <= 46))
                {
                    stringBuilder.Append((char)b);
                }
                else if (b == 32)
                {
                    stringBuilder.Append('+');
                }
                else
                {
                    stringBuilder.Append("%" + b.ToString(format));
                }
            }
            return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
        }

        public static string UrlDecode(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return null;
            }
            List<byte> list = new List<byte>();
            int length = text.Length;
            for (int i = 0; i < length; i++)
            {
                char c = text[i];
                switch (c)
                {
                    case '+':
                        list.Add(32);
                        break;

                    case '%':
                        {
                            byte item = Convert.ToByte(text.Substring(i + 1, 2), 16);
                            list.Add(item);
                            i += 2;
                            break;
                        }
                    default:
                        list.Add((byte)c);
                        break;
                }
            }
            byte[] array = list.ToArray();
            return Encoding.UTF8.GetString(array, 0, array.Length);
        }

        public static string HexUnescape(this string text, params char[] anyCharOf)
        {
            if (string.IsNullOrEmpty(text))
            {
                return null;
            }
            if (anyCharOf == null || anyCharOf.Length == 0)
            {
                return text;
            }
            StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
            int length = text.Length;
            for (int i = 0; i < length; i++)
            {
                string text2 = text.Substring(i, 1);
                if (text2 == "%")
                {
                    int num = Convert.ToInt32(text.Substring(i + 1, 2), 16);
                    stringBuilder.Append((char)num);
                    i += 2;
                }
                else
                {
                    stringBuilder.Append(text2);
                }
            }
            return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
        }

        public static string UrlFormat(this string url, params string[] urlComponents)
        {
            string[] array = new string[urlComponents.Length];
            for (int i = 0; i < urlComponents.Length; i++)
            {
                string text = urlComponents[i];
                array[i] = text.UrlEncode();
            }
            object[] args = array;
            return string.Format(url, args);
        }

        public static string ToRot13(this string value)
        {
            char[] array = value.ToCharArray();
            for (int i = 0; i < array.Length; i++)
            {
                int num = array[i];
                if (num >= 97 && num <= 122)
                {
                    num += ((num > 109) ? (-13) : 13);
                }
                else if (num >= 65 && num <= 90)
                {
                    num += ((num > 77) ? (-13) : 13);
                }
                array[i] = (char)num;
            }
            return new string(array);
        }

        public static string UrlWithTrailingSlash(this string url)
        {
            int num = url?.IndexOfAny(UrlPathDelims) ?? (-1);
            if (num < 0)
            {
                return url.WithTrailingSlash();
            }
            return url.Substring(0, num).WithTrailingSlash() + url.Substring(num);
        }

        public static string WithTrailingSlash(this string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            if (path == "")
            {
                return "/";
            }
            if (path[path.Length - 1] == '/')
            {
                return path;
            }
            return path + "/";
        }

        public static string AppendPath(this string uri, params string[] uriComponents)
        {
            return uri.AppendUrlPaths(uriComponents);
        }

        public static string AppendUrlPaths(this string uri, params string[] uriComponents)
        {
            StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
            stringBuilder.Append(uri.WithTrailingSlash());
            int num = 0;
            foreach (string text in uriComponents)
            {
                if (num++ > 0)
                {
                    stringBuilder.Append('/');
                }
                stringBuilder.Append(text.UrlEncode());
            }
            return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
        }

        public static string AppendUrlPathsRaw(this string uri, params string[] uriComponents)
        {
            StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
            stringBuilder.Append(uri.WithTrailingSlash());
            int num = 0;
            foreach (string value in uriComponents)
            {
                if (num++ > 0)
                {
                    stringBuilder.Append('/');
                }
                stringBuilder.Append(value);
            }
            return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
        }

        public static string FromUtf8Bytes(this byte[] bytes)
        {
            if (bytes != null)
            {
                if (bytes.Length <= 3 || bytes[0] != 239 || bytes[1] != 187 || bytes[2] != 191)
                {
                    return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                }
                return Encoding.UTF8.GetString(bytes, 3, bytes.Length - 3);
            }
            return null;
        }

        public static byte[] ToUtf8Bytes(this string value)
        {
            return Encoding.UTF8.GetBytes(value);
        }

        public static byte[] ToUtf8Bytes(this int intVal)
        {
            return FastToUtf8Bytes(intVal.ToString());
        }

        public static byte[] ToUtf8Bytes(this long longVal)
        {
            return FastToUtf8Bytes(longVal.ToString());
        }

        public static byte[] ToUtf8Bytes(this ulong ulongVal)
        {
            return FastToUtf8Bytes(ulongVal.ToString());
        }

        public static string WithoutBom(this string value)
        {
            if (value.Length <= 0 || value[0] != '\ufeff')
            {
                return value;
            }
            return value.Substring(1);
        }

        public static string ToBase64UrlSafe(this byte[] input)
        {
            return Convert.ToBase64String(input).LeftPart('=').Replace('+', '-')
                .Replace('/', '_');
        }

        public static byte[] FromBase64UrlSafe(this string input)
        {
            string text = input;
            text = text.Replace('-', '+');
            text = text.Replace('_', '/');
            switch (text.Length % 4)
            {
                case 2:
                    text += "==";
                    break;

                case 3:
                    text += "=";
                    break;

                default:
                    throw new Exception("Illegal base64url string!");
                case 0:
                    break;
            }
            return Convert.FromBase64String(text);
        }

        //
        // 摘要:
        //     Skip the encoding process for 'safe strings'
        //
        // 参数:
        //   strVal:
        private static byte[] FastToUtf8Bytes(string strVal)
        {
            byte[] array = new byte[strVal.Length];
            for (int i = 0; i < strVal.Length; i++)
            {
                array[i] = (byte)strVal[i];
            }
            return array;
        }

        public static string LeftPart(this string strVal, char needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.IndexOf(needle);
            if (num != -1)
            {
                return strVal.Substring(0, num);
            }
            return strVal;
        }

        public static string LeftPart(this string strVal, string needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
            if (num != -1)
            {
                return strVal.Substring(0, num);
            }
            return strVal;
        }

        public static string RightPart(this string strVal, char needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.IndexOf(needle);
            if (num != -1)
            {
                return strVal.Substring(num + 1);
            }
            return strVal;
        }

        public static string RightPart(this string strVal, string needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
            if (num != -1)
            {
                return strVal.Substring(num + needle.Length);
            }
            return strVal;
        }

        public static string LastLeftPart(this string strVal, char needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.LastIndexOf(needle);
            if (num != -1)
            {
                return strVal.Substring(0, num);
            }
            return strVal;
        }

        public static string LastLeftPart(this string strVal, string needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.LastIndexOf(needle, StringComparison.OrdinalIgnoreCase);
            if (num != -1)
            {
                return strVal.Substring(0, num);
            }
            return strVal;
        }

        public static string LastRightPart(this string strVal, char needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.LastIndexOf(needle);
            if (num != -1)
            {
                return strVal.Substring(num + 1);
            }
            return strVal;
        }

        public static string LastRightPart(this string strVal, string needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.LastIndexOf(needle, StringComparison.OrdinalIgnoreCase);
            if (num != -1)
            {
                return strVal.Substring(num + needle.Length);
            }
            return strVal;
        }

        public static string[] SplitOnFirst(this string strVal, char needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.IndexOf(needle);
            if (num == -1)
            {
                return new string[1]
                {
                    strVal
                };
            }
            return new string[2]
            {
                strVal.Substring(0, num),
                strVal.Substring(num + 1)
            };
        }

        public static string[] SplitOnFirst(this string strVal, string needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
            if (num == -1)
            {
                return new string[1]
                {
                    strVal
                };
            }
            return new string[2]
            {
                strVal.Substring(0, num),
                strVal.Substring(num + needle.Length)
            };
        }

        public static string[] SplitOnLast(this string strVal, char needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.LastIndexOf(needle);
            if (num == -1)
            {
                return new string[1]
                {
                    strVal
                };
            }
            return new string[2]
            {
                strVal.Substring(0, num),
                strVal.Substring(num + 1)
            };
        }

        public static string[] SplitOnLast(this string strVal, string needle)
        {
            if (strVal == null)
            {
                return null;
            }
            int num = strVal.LastIndexOf(needle, StringComparison.OrdinalIgnoreCase);
            if (num == -1)
            {
                return new string[1]
                {
                    strVal
                };
            }
            return new string[2]
            {
                strVal.Substring(0, num),
                strVal.Substring(num + needle.Length)
            };
        }

        public static string GetExtension(this string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                return null;
            }
            int num = filePath.LastIndexOf('.');
            if (num != -1)
            {
                return filePath.Substring(num);
            }
            return string.Empty;
        }

        public static string FormatWith(this string text, params object[] args)
        {
            return string.Format(text, args);
        }

        public static string Fmt(this string text, params object[] args)
        {
            return string.Format(text, args);
        }

        public static string Fmt(this string text, IFormatProvider provider, params object[] args)
        {
            return string.Format(provider, text, args);
        }

        public static string Fmt(this string text, object arg1)
        {
            return string.Format(text, arg1);
        }

        public static string Fmt(this string text, object arg1, object arg2)
        {
            return string.Format(text, arg1, arg2);
        }

        public static string Fmt(this string text, object arg1, object arg2, object arg3)
        {
            return string.Format(text, arg1, arg2, arg3);
        }

        public static int IndexOfAny(this string text, int startIndex, params string[] needles)
        {
            int num = -1;
            if (text != null)
            {
                foreach (string value in needles)
                {
                    int num2 = text.IndexOf(value, startIndex, StringComparison.Ordinal);
                    if (num2 >= 0 && (num == -1 || num2 < num))
                    {
                        num = num2;
                    }
                }
            }
            return num;
        }

        public static string ExtractContents(this string fromText, string startAfter, string endAt)
        {
            return fromText.ExtractContents(startAfter, startAfter, endAt);
        }

        public static string ExtractContents(this string fromText, string uniqueMarker, string startAfter, string endAt)
        {
            if (string.IsNullOrEmpty(uniqueMarker))
            {
                throw new ArgumentNullException("uniqueMarker");
            }
            if (string.IsNullOrEmpty(startAfter))
            {
                throw new ArgumentNullException("startAfter");
            }
            if (string.IsNullOrEmpty(endAt))
            {
                throw new ArgumentNullException("endAt");
            }
            if (string.IsNullOrEmpty(fromText))
            {
                return null;
            }
            int num = fromText.IndexOf(uniqueMarker, StringComparison.Ordinal);
            if (num == -1)
            {
                return null;
            }
            int num2 = fromText.IndexOf(startAfter, num, StringComparison.Ordinal);
            if (num2 == -1)
            {
                return null;
            }
            num2 += startAfter.Length;
            int num3 = fromText.IndexOf(endAt, num2, StringComparison.Ordinal);
            if (num3 == -1)
            {
                num3 = fromText.Length;
            }
            return fromText.Substring(num2, num3 - num2);
        }

        public static string StripHtml(this string html)
        {
            if (!string.IsNullOrEmpty(html))
            {
                return StripHtmlRegEx.Replace(html, "");
            }
            return null;
        }

        public static string Quoted(this string text)
        {
            if (text != null && text.IndexOf('"') < 0)
            {
                return "\"" + text + "\"";
            }
            return text;
        }

        public static string StripQuotes(this string text)
        {
            if (!string.IsNullOrEmpty(text) && text.Length >= 2)
            {
                if ((text[0] != '"' || text[text.Length - 1] != '"') && (text[0] != '\'' || text[text.Length - 1] != '\''))
                {
                    return text;
                }
                return text.Substring(1, text.Length - 2);
            }
            return text;
        }

        public static string StripMarkdownMarkup(this string markdown)
        {
            if (string.IsNullOrEmpty(markdown))
            {
                return null;
            }
            markdown = StripBracketsRegEx.Replace(markdown, "");
            markdown = StripBracesRegEx.Replace(markdown, "");
            markdown = markdown.Replace("*", "").Replace("!", "").Replace("\r", "")
                .Replace("\n", "")
                .Replace("#", "");
            return markdown;
        }

        public static string ToCamelCase(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return value;
            }
            int length = value.Length;
            char[] array = new char[length];
            bool flag = true;
            for (int i = 0; i < length; i++)
            {
                char c = value[i];
                char c2 = (i < length - 1) ? value[i + 1] : 'A';
                bool flag2 = c >= 'A' && c <= 'Z';
                bool flag3 = c2 >= 'A' && c2 <= 'Z';
                if (flag && flag2 && (flag3 || i == 0))
                {
                    c = (char)(c + 32);
                }
                else
                {
                    flag = false;
                }
                array[i] = c;
            }
            return new string(array);
        }

        public static string ToPascalCase(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return value;
            }
            if (value.IndexOf('_') >= 0)
            {
                string[] array = value.Split('_');
                StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
                string[] array2 = array;
                foreach (string value2 in array2)
                {
                    if (!string.IsNullOrEmpty(value2))
                    {
                        string text = value2.ToCamelCase();
                        stringBuilder.Append(char.ToUpper(text[0]).ToString() + text.SafeSubstring(1, text.Length));
                    }
                }
                return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
            }
            string text2 = value.ToCamelCase();
            return char.ToUpper(text2[0]).ToString() + text2.SafeSubstring(1, text2.Length);
        }

        public static string ToLowercaseUnderscore(this string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return value;
            }
            value = value.ToCamelCase();
            StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
            string text = value;
            foreach (char c in text)
            {
                if (char.IsDigit(c) || (char.IsLetter(c) && char.IsLower(c)) || c == '_')
                {
                    stringBuilder.Append(c);
                    continue;
                }
                stringBuilder.Append("_");
                stringBuilder.Append(char.ToLower(c));
            }
            return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
        }

        public static string ToLowerSafe(this string value)
        {
            return value?.ToLower();
        }

        public static string ToUpperSafe(this string value)
        {
            return value?.ToUpper();
        }

        public static string SafeSubstring(this string value, int startIndex)
        {
            if (string.IsNullOrEmpty(value))
            {
                return string.Empty;
            }
            return value.SafeSubstring(startIndex, value.Length);
        }

        public static string SafeSubstring(this string value, int startIndex, int length)
        {
            if (string.IsNullOrEmpty(value) || length <= 0)
            {
                return string.Empty;
            }
            if (startIndex < 0)
            {
                startIndex = 0;
            }
            if (value.Length >= startIndex + length)
            {
                return value.Substring(startIndex, length);
            }
            if (value.Length <= startIndex)
            {
                return string.Empty;
            }
            return value.Substring(startIndex);
        }

        [Obsolete("typo")]
        public static string SubstringWithElipsis(this string value, int startIndex, int length)
        {
            return value.SubstringWithEllipsis(startIndex, length);
        }

        public static string SubstringWithEllipsis(this string value, int startIndex, int length)
        {
            string text = value.SafeSubstring(startIndex, length);
            if (text.Length != length)
            {
                return text;
            }
            return text + "...";
        }

        public static T _ToEnum<T>(this string value)
        {
            return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
        }

        public static T ToEnumOrDefault<T>(this string value, T defaultValue)
        {
            if (string.IsNullOrEmpty(value))
            {
                return defaultValue;
            }
            return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
        }

        public static string SplitCamelCase(this string value)
        {
            return SplitCamelCaseRegex.Replace(value, " $1").TrimStart();
        }

        public static string ToHttps(this string url)
        {
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }
            return HttpRegex.Replace(url.Trim(), "https://");
        }

        public static bool IsEmpty(this string value)
        {
            return string.IsNullOrEmpty(value);
        }

        public static bool IsNullOrEmpty(this string value)
        {
            return string.IsNullOrEmpty(value);
        }

        public static bool EqualsIgnoreCase(this string value, string other)
        {
            return string.Equals(value, other, StringComparison.OrdinalIgnoreCase);
        }

        public static string ReplaceFirst(this string haystack, string needle, string replacement)
        {
            int num = haystack.IndexOf(needle, StringComparison.Ordinal);
            if (num < 0)
            {
                return haystack;
            }
            return haystack.Substring(0, num) + replacement + haystack.Substring(num + needle.Length);
        }

        public static string ReplaceAll(this string haystack, string needle, string replacement)
        {
            if (needle == replacement)
            {
                return haystack;
            }
            int num;
            while ((num = haystack.IndexOf(needle, StringComparison.Ordinal)) >= 0)
            {
                haystack = haystack.Substring(0, num) + replacement + haystack.Substring(num + needle.Length);
            }
            return haystack;
        }

        public static bool ContainsAny(this string text, params string[] testMatches)
        {
            foreach (string value in testMatches)
            {
                if (text.Contains(value))
                {
                    return true;
                }
            }
            return false;
        }

        public static bool ContainsAny(this string text, string[] testMatches, StringComparison comparisonType)
        {
            foreach (string value in testMatches)
            {
                if (text.IndexOf(value, comparisonType) >= 0)
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsValidVarName(this string name)
        {
            return InvalidVarCharsRegex.IsMatch(name);
        }

        public static string SafeVarName(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return null;
            }
            return InvalidVarCharsRegex.Replace(text, "_");
        }

        public static string SafeVarRef(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return null;
            }
            return InvalidVarRefCharsRegex.Replace(text, "_");
        }

        public static string Join(this List<string> items)
        {
            return string.Join(",", items.ToArray());
        }

        public static string Join(this List<string> items, string delimeter)
        {
            return string.Join(delimeter, items.ToArray());
        }

        public static string ToParentPath(this string path)
        {
            int num = path.LastIndexOf('/');
            if (num == -1)
            {
                return "/";
            }
            return path.Substring(0, num);
        }

        public static string RemoveCharFlags(this string text, bool[] charFlags)
        {
            if (text == null)
            {
                return null;
            }
            char[] array = text.ToCharArray();
            int length = 0;
            foreach (char c in text)
            {
                if (c >= charFlags.Length || !charFlags[c])
                {
                    array[length++] = c;
                }
            }
            return new string(array, 0, length);
        }

        public static string ToNullIfEmpty(this string text)
        {
            if (!string.IsNullOrEmpty(text))
            {
                return text;
            }
            return null;
        }

        public static bool IsUserType(this Type type)
        {
            if (type.IsClass)
            {
                return !type.IsSystemType();
            }
            return false;
        }

        public static bool IsUserEnum(this Type type)
        {
            if (type.IsEnum)
            {
                return !type.IsSystemType();
            }
            return false;
        }

        public static bool IsSystemType(this Type type)
        {
            if (type.Namespace != null && !type.Namespace!.StartsWith("System"))
            {
                return type.Name.IndexOfAny(SystemTypeChars) >= 0;
            }
            return true;
        }

        public static bool IsTuple(this Type type)
        {
            return type.Name.StartsWith("Tuple`");
        }

        public static bool IsInt(this string text)
        {
            int result;
            if (!string.IsNullOrEmpty(text))
            {
                return int.TryParse(text, out result);
            }
            return false;
        }

        public static int ToInt(this string text)
        {
            if (text != null)
            {
                return int.Parse(text);
            }
            return 0;
        }

        public static int ToInt(this string text, int defaultValue)
        {
            if (!int.TryParse(text, out int result))
            {
                return defaultValue;
            }
            return result;
        }

        public static long ToInt64(this string text)
        {
            return long.Parse(text);
        }

        public static long ToInt64(this string text, long defaultValue)
        {
            if (!long.TryParse(text, out long result))
            {
                return defaultValue;
            }
            return result;
        }

        public static float ToFloat(this string text)
        {
            if (text != null)
            {
                return float.Parse(text);
            }
            return 0f;
        }

        public static float ToFloat(this string text, float defaultValue)
        {
            if (!float.TryParse(text, out float result))
            {
                return defaultValue;
            }
            return result;
        }

        public static double ToDouble(this string text)
        {
            if (text != null)
            {
                return double.Parse(text);
            }
            return 0.0;
        }

        public static double ToDouble(this string text, double defaultValue)
        {
            if (!double.TryParse(text, out double result))
            {
                return defaultValue;
            }
            return result;
        }

        public static decimal ToDecimal(this string text)
        {
            if (text != null)
            {
                return decimal.Parse(text);
            }
            return 0m;
        }

        public static decimal ToDecimal(this string text, decimal defaultValue)
        {
            if (!decimal.TryParse(text, out decimal result))
            {
                return defaultValue;
            }
            return result;
        }

        public static bool Matches(this string value, string pattern)
        {
            return value.Glob(pattern);
        }

        public static bool Glob(this string value, string pattern)
        {
            int i;
            for (i = 0; pattern.Length != i; i++)
            {
                switch (pattern[i])
                {
                    case '*':
                        {
                            for (int num = value.Length; num >= i; num--)
                            {
                                if (value.Substring(num).Glob(pattern.Substring(i + 1)))
                                {
                                    return true;
                                }
                            }
                            return false;
                        }
                    default:
                        if (value.Length == i || char.ToUpper(pattern[i]) != char.ToUpper(value[i]))
                        {
                            return false;
                        }
                        break;

                    case '?':
                        break;
                }
            }
            return value.Length == i;
        }

        public static bool GlobPath(this string filePath, string pattern)
        {
            if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(pattern))
            {
                return false;
            }
            string text = filePath.Replace('\\', '/');
            if (text[0] == '/')
            {
                text = text.Substring(1);
            }
            string text2 = pattern.Replace('\\', '/');
            if (text2[0] == '/')
            {
                text2 = text2.Substring(1);
            }
            if (text2.IndexOf('*') == -1 && text2.IndexOf('?') == -1)
            {
                return text == text2;
            }
            string[] array = text2.SplitOnLast('/');
            string[] array2 = text.SplitOnLast('/');
            if (array2.Length == 1)
            {
                return array2[0].Glob(pattern);
            }
            string text3 = array2[0];
            string value = array2[1];
            if (array.Length == 1)
            {
                return value.Glob(array[0]);
            }
            string text4 = array[0];
            string pattern2 = array[1];
            if (text4.IndexOf("**", StringComparison.Ordinal) >= 0)
            {
                if (!text.StartsWith(text4.LeftPart("**").TrimEnd('*', '/')))
                {
                    return false;
                }
            }
            else if (text4.IndexOf('*') >= 0 || text4.IndexOf('?') >= 0)
            {
                if (!new Regex("^" + Regex.Escape(text4).Replace("\\*", "[^\\/]*").Replace("\\?", ".") + "$").IsMatch(text3))
                {
                    return false;
                }
            }
            else if (text3 != text4)
            {
                return false;
            }
            return value.Glob(pattern2);
        }

        public static string TrimPrefixes(this string fromString, params string[] prefixes)
        {
            if (string.IsNullOrEmpty(fromString))
            {
                return fromString;
            }
            foreach (string text in prefixes)
            {
                if (fromString.StartsWith(text))
                {
                    return fromString.Substring(text.Length);
                }
            }
            return fromString;
        }

        public static Dictionary<string, string> ParseKeyValueText(this string text, string delimiter = " ")
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            if (text == null)
            {
                return dictionary;
            }
            foreach (string[] item in text.ReadLines().Select((Func<string, string[]>)((string line) => line.Trim().SplitOnFirst(delimiter))))
            {
                string text2 = item[0].Trim();
                if (text2.Length != 0 && !text2.StartsWith("#"))
                {
                    dictionary[text2] = ((item.Length == 2) ? item[1].Trim() : null);
                }
            }
            return dictionary;
        }

        public static List<KeyValuePair<string, string>> ParseAsKeyValues(this string text, string delimiter = " ")
        {
            List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
            if (text == null)
            {
                return list;
            }
            foreach (string[] item in text.ReadLines().Select((Func<string, string[]>)((string line) => line.Trim().SplitOnFirst(delimiter))))
            {
                string text2 = item[0].Trim();
                if (text2.Length != 0 && !text2.StartsWith("#"))
                {
                    list.Add(new KeyValuePair<string, string>(text2, (item.Length == 2) ? item[1].Trim() : null));
                }
            }
            return list;
        }

        public static IEnumerable<string> ReadLines(this string text)
        {
            StringReader reader = new StringReader(text ?? "");
            string text2;
            while ((text2 = reader.ReadLine()) != null)
            {
                yield return text2;
            }
        }

        public static string NormalizeNewLines(this string text)
        {
            return text?.Replace("\r\n", "\n").Trim();
        }

        public static string HexEscape(this string text, params char[] anyCharOf)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }
            if (anyCharOf == null || anyCharOf.Length == 0)
            {
                return text;
            }
            HashSet<char> hashSet = new HashSet<char>(anyCharOf);
            StringBuilder stringBuilder = StringBuilderThreadStatic.Allocate();
            int length = text.Length;
            for (int i = 0; i < length; i++)
            {
                char c = text[i];
                if (hashSet.Contains(c))
                {
                    int num = c;
                    stringBuilder.Append("%" + num.ToString("x"));
                }
                else
                {
                    stringBuilder.Append(c);
                }
            }
            return StringBuilderThreadStatic.ReturnAndFree(stringBuilder);
        }
    }

    internal static class StringBuilderThreadStatic
    {
        [ThreadStatic]
        private static StringBuilder cache;

        public static StringBuilder Allocate()
        {
            StringBuilder stringBuilder = cache;
            if (stringBuilder == null)
            {
                return new StringBuilder();
            }
            stringBuilder.Length = 0;
            cache = null;
            return stringBuilder;
        }

        public static void Free(StringBuilder sb)
        {
            cache = sb;
        }

        public static string ReturnAndFree(StringBuilder sb)
        {
            string result = sb.ToString();
            cache = sb;
            return result;
        }
    }
}